package com.grad.why.studentsystem.controller;

import com.grad.why.studentsystem.domain.*;
import com.grad.why.studentsystem.domain.current.CurrentStudentEvaluateInfo;
import com.grad.why.studentsystem.mapper.CoursestandardMapper;
import com.grad.why.studentsystem.service.*;
import com.grad.why.studentsystem.util.MyStudentEvaluateCompareble;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Controller
@RequestMapping("/studentManageSystem")
public class StudentEvaluateScoreController {
    @Autowired
    private ChooseCourseService chooseCourseService;

    @Autowired
    private CourseStandardService courseStandardService;

    @Autowired
    private StudentService studentService;

    @Autowired
    private ClassinfoService classinfoService;

    @Autowired
    private IndexInfoService indexinfoService;



    @RequestMapping("/getStudentEvaluateInfos")
    @ResponseBody
    public Object test(
            @RequestParam(required = false, defaultValue = "0", value = "offset") int offset,
            @RequestParam(required = false, defaultValue = "10", value = "limit") int limit,
            @RequestParam(required = false, value = "sort") String sort,
            @RequestParam(required = false, defaultValue = "", value = "search") String search,
            @RequestParam(required = false, value = "order") String order
    ){
        List<CurrentStudentEvaluateInfo> rows = new ArrayList<>();
        List<Student> students = studentService.getStudentList(offset,limit,sort,search);
        long total = studentService.getStudentListLength(search);
        for(int p = 0;p<students.size();p++){
            int projectid = classinfoService.getClassInfosByPrimaryKey(students.get(p).getClassid()).getProjectid();
            //获取一级能力点数目
            int firstIndexCount = indexinfoService.getFirstIndexCountByProjectId(projectid);
            //获取二级能力点数目
            int secondIndexCount = indexinfoService.getSecondIndexCountByProjectId(projectid);
            //定义权重数组
            double[][] W = new double[firstIndexCount][secondIndexCount];
            //根据专业编号拿权重
            List<Indexweights> indexweights = indexinfoService.getIndexWeightByProjectId(projectid);

            //设置权重
            for(int i = 0;i<indexweights.size();i++){
                W[i/7][i%7] = indexweights.get(i).getValue();
            }

            //定义实时学生专业能力信息
            CurrentStudentEvaluateInfo currentStudentEvaluateInfo = new CurrentStudentEvaluateInfo();
            Student student = students.get(p);

            //设置基本信息
            currentStudentEvaluateInfo.setSid(student.getId());
            currentStudentEvaluateInfo.setSname(student.getName());
            currentStudentEvaluateInfo.setClassName(classinfoService.getClassInfosByPrimaryKey(student.getClassid()).getClassname());

            List<ChooseCourse> chooseCourses = chooseCourseService.getChooseCoursesBySid(student.getId());
            List<Coursestandard> coursestandards = new ArrayList<Coursestandard>();

            for(ChooseCourse c : chooseCourses){
                Coursestandard coursestandard = courseStandardService.getCourseStandardInfoById(c.getCid());
                coursestandards.add(coursestandard);
            }

            //C[二级能力点数目][评价等级5]
            int[][] C = new int[W[0].length][5];
            for(int i = 0;i<C.length;i++){
                for(int j = 0;j<C[0].length;j++){
                    C[i][j] = 0;
                }
            }

            for(int i = 0;i<chooseCourses.size();i++){
                ChooseCourse chooseCourse = chooseCourses.get(i);
                Coursestandard coursestandard = coursestandards.get(i);
                float[] choose_course = SerilizebleChooseCourse(chooseCourse);
                float[] course_standard = SerilizebleCourseStandard(coursestandard);
                for(int j = 0;j<W[0].length;j++){
                    if(course_standard[j] == 0){
                        continue;
                    }else{
                        int level = getLevelByValue(choose_course[j] / course_standard[j]);
                        C[j][level] += 1;
                    }
                }
            }

            float[][] R = new float[C.length][C[0].length];
            for(int i = 0;i<R.length;i++){
                for(int j = 0;j<R[0].length;j++){
                    R[i][j] = 0;
                }
            }

            for(int i = 0;i<R.length;i++){
                for(int j = 0;j<R[0].length;j++){
                    float sum = 0;
                    for(int k = 0;k<R.length;k++){
                        sum += C[k][j];
                    }
                    if(sum == 0){
                        R[i][j] = 0;
                    }else {
                        R[i][j] = C[i][j] / sum;
                    }
                }
            }

            float[][] U = new float[W.length][R[0].length];
            for(int i = 0;i<U.length;i++){
                for(int j = 0;U[0].length<5;j++){
                    U[i][j] = 0;
                }
            }

            for(int i= 0;i<U.length;i++){
                for(int j = 0;j<R.length;j++){
                    for(int k = 0;k<U[0].length;k++){
                        U[i][k] += W[i][j] * R[j][k];
                    }
                }
            }

            float[][] E = new float[U.length][U[0].length];
            for(int i = 0;i<E.length;i++){
                for(int j = 0;j<E[0].length;j++){
                    E[i][j] = 0;
                }
            }

            for(int i = 0;i<E.length;i++){
                for(int j = 0;j<E[0].length;j++){
                    float sum = 0;
                    for(int k = 0;k<E.length;k++){
                        sum += U[k][j];
                    }
                    if(sum == 0){
                        E[i][j] = 0;
                    }else{
                        E[i][j] = U[i][j] / sum;
                    }
                }
            }
            float[][] V = {{1.0f},{0.8f},{0.5f},{0.3f},{0.1f}};
            float[][] B = new float[W.length][1];
            for(int i = 0;i<B.length;i++){
                B[i][0] = 0;
            }
            for(int i= 0;i<W.length;i++){
                for(int j = 0;j<V.length;j++){
                    for(int k = 0;k<V[0].length;k++){
                        B[i][k] += E[i][j] * V[j][k];
                    }
                }
            }

            if(W.length == 1){
                currentStudentEvaluateInfo.setP1(B[0][0] * 100);
                currentStudentEvaluateInfo.setAve((B[0][0]) * 100/1.0f);
            }else if(W.length == 2){
                currentStudentEvaluateInfo.setP1(B[0][0] * 100);
                currentStudentEvaluateInfo.setP2(B[1][0] * 100);
                currentStudentEvaluateInfo.setAve((B[0][0]+B[1][0]) * 100/2.0f);
            }else if(W.length == 3){
                currentStudentEvaluateInfo.setP1(B[0][0] * 100);
                currentStudentEvaluateInfo.setP2(B[1][0] * 100);
                currentStudentEvaluateInfo.setP3(B[2][0] * 100);
                currentStudentEvaluateInfo.setAve((B[0][0]+B[1][0]+B[2][0]) * 100/3.0f);
            }else if(W.length == 4){
                currentStudentEvaluateInfo.setP1(B[0][0] * 100);
                currentStudentEvaluateInfo.setP2(B[1][0] * 100);
                currentStudentEvaluateInfo.setP3(B[2][0] * 100);
                currentStudentEvaluateInfo.setP4(B[3][0] * 100);
                currentStudentEvaluateInfo.setAve((B[0][0]+B[1][0]+B[2][0]+B[3][0]) * 100/4.0f);
            }else if(W.length == 5){
                currentStudentEvaluateInfo.setP1(B[0][0] * 100);
                currentStudentEvaluateInfo.setP2(B[1][0] * 100);
                currentStudentEvaluateInfo.setP3(B[2][0] * 100);
                currentStudentEvaluateInfo.setP4(B[3][0] * 100);
                currentStudentEvaluateInfo.setP5(B[4][0] * 100);
                currentStudentEvaluateInfo.setAve((B[0][0]+B[1][0]+B[2][0]+B[3][0]+B[4][0]) * 100/5.0f);
            }else if(W.length == 6){
                currentStudentEvaluateInfo.setP1(B[0][0] * 100);
                currentStudentEvaluateInfo.setP2(B[1][0] * 100);
                currentStudentEvaluateInfo.setP3(B[2][0] * 100);
                currentStudentEvaluateInfo.setP4(B[3][0] * 100);
                currentStudentEvaluateInfo.setP5(B[4][0] * 100);
                currentStudentEvaluateInfo.setP6(B[5][0] * 100);
                currentStudentEvaluateInfo.setAve((B[0][0]+B[1][0]+B[2][0]+B[3][0]+B[4][0]+B[5][0]) * 100/6.0f);
            }

            rows.add(currentStudentEvaluateInfo);
        }
        Collections.sort(rows,new MyStudentEvaluateCompareble());
        for(int i = 0;i<rows.size();i++){
            rows.get(i).setRank(i+1);
        }
        Map<String, Object> result = new HashMap<>(2);
        result.put("rows", rows);
        result.put("total", total);
        return result;
    }

//
//    @RequestMapping("/getStudentEvaluateInfos")
//    @ResponseBody
//    public Object evaluate(
//            @RequestParam(required = false, defaultValue = "0", value = "offset") int offset,
//            @RequestParam(required = false, defaultValue = "10", value = "limit") int limit,
//            @RequestParam(required = false, value = "sort") String sort,
//            @RequestParam(required = false, defaultValue = "", value = "search") String search,
//            @RequestParam(required = false, value = "order") String order
//    ){
//        double[][] W = {{0.1429,0.0357,0.1786,0.0714,0.0357,0.2500,0.2857},
//                {0.2500,0.0357,0.1429,0.0714,0.1071,0.2143,0.1786},
//                {0.2142,0.1786,0.1429,0.0357,0.1071,0.1429,0.1786},
//                {0.2857,0.0357,0.1786,0.1786,0.1429,0.0714,0.1071}};
//        List<CurrentStudentEvaluateInfo> rows = new ArrayList<>();
//
//        List<Student> students = studentService.getStudentList(offset,limit,sort,search);
//        long total = studentService.getStudentListLength(search);
//
//        for(int p = 0;p<students.size();p++){
//            CurrentStudentEvaluateInfo currentStudentEvaluateInfo = new CurrentStudentEvaluateInfo();
//            Student student = students.get(p);
//
//            //设置基本信息
//            currentStudentEvaluateInfo.setSid(student.getId());
//            currentStudentEvaluateInfo.setSname(student.getName());
//            currentStudentEvaluateInfo.setClassName(classinfoService.getClassInfosByPrimaryKey(student.getClassid()).getClassname());
//
//            List<ChooseCourse> chooseCourses = chooseCourseService.getChooseCoursesBySid(student.getId());
//            List<Coursestandard> coursestandards = new ArrayList<Coursestandard>();
//
//            for(ChooseCourse c : chooseCourses){
//                Coursestandard coursestandard = courseStandardService.getCourseStandardInfoById(c.getCid());
//                coursestandards.add(coursestandard);
//            }
//            int[][] C = new int[W[0].length][5];
//            for(int i = 0;i<C.length;i++){
//                for(int j = 0;j<C[0].length;j++){
//                    C[i][j] = 0;
//                }
//            }
//
//            for(int i = 0;i<chooseCourses.size();i++){
//                ChooseCourse chooseCourse = chooseCourses.get(i);
//                Coursestandard coursestandard = coursestandards.get(i);
//                float[] choose_course = SerilizebleChooseCourse(chooseCourse);
//                float[] course_standard = SerilizebleCourseStandard(coursestandard);
//                for(int j = 0;j<W[0].length;j++){
//                    if(course_standard[j] == 0){
//                        continue;
//                    }else{
//                        int level = getLevelByValue(choose_course[j] / course_standard[j]);
//                        C[j][level] += 1;
//                    }
//                }
//            }
//
//            float[][] R = new float[W[0].length][5];
//            for(int i = 0;i<R.length;i++){
//                for(int j = 0;j<R[0].length;j++){
//                    R[i][j] = 0;
//                }
//            }
//
//            for(int i = 0;i<R.length;i++){
//                for(int j = 0;j<R[0].length;j++){
//                    float sum = 0;
//                    for(int k = 0;k<R.length;k++){
//                        sum += C[k][j];
//                    }
//                    if(sum == 0){
//                        R[i][j] = 0;
//                    }else {
//                        R[i][j] = C[i][j] / sum;
//                    }
//                }
//            }
//
//            float[][] U = new float[W.length][5];
//            for(int i = 0;i<4;i++){
//                for(int j = 0;j<5;j++){
//                    U[i][j] = 0;
//                }
//            }
//
//            for(int i= 0;i<4;i++){
//                for(int j = 0;j<7;j++){
//                    for(int k = 0;k<5;k++){
//                        U[i][k] += W[i][j] * R[j][k];
//                    }
//                }
//            }
//
//            float[][] E = new float[W.length][5];
//            for(int i = 0;i<E.length;i++){
//                for(int j = 0;j<E[0].length;j++){
//                    E[i][j] = 0;
//                }
//            }
//
//            for(int i = 0;i<E.length;i++){
//                for(int j = 0;j<E[0].length;j++){
//                    float sum = 0;
//                    for(int k = 0;k<E.length;k++){
//                        sum += U[k][j];
//                    }
//                    if(sum == 0){
//                        E[i][j] = 0;
//                    }else{
//                        E[i][j] = U[i][j] / sum;
//                    }
//                }
//            }
//
//            float[][] V = {{1.0f},{0.8f},{0.5f},{0.3f},{0.1f}};
//            float[][] B = new float[W.length][1];
//
//            for(int i = 0;i<B.length;i++){
//                B[i][0] = 0;
//            }
//
//            for(int i= 0;i<W.length;i++){
//                for(int j = 0;j<V.length;j++){
//                    for(int k = 0;k<V[0].length;k++){
//                        B[i][k] += E[i][j] * V[j][k];
//                    }
//                }
//            }
//
//            currentStudentEvaluateInfo.setP1(B[0][0] * 100);
//            currentStudentEvaluateInfo.setP2(B[1][0] * 100);
//            currentStudentEvaluateInfo.setP3(B[2][0] * 100);
//            currentStudentEvaluateInfo.setP4(B[3][0] * 100);
//            currentStudentEvaluateInfo.setAve((B[0][0] + B[1][0] + B[2][0] + B[3][0]) * 100/4.0f);
//
//            rows.add(currentStudentEvaluateInfo);
//        }
//
//        Collections.sort(rows,new MyStudentEvaluateCompareble());
//
//        Map<String, Object> result = new HashMap<>(2);
//        result.put("rows", rows);
//        result.put("total", total);
//        return result;
//    }

    public int getLevelByValue(float v) {
        if(v <= 0.6){
            return 4;
        }else if(v > 0.6 && v <= 0.7){
            return 3;
        }else if(v > 0.7 && v <= 0.8){
            return 2;
        }else if(v > 0.8 && v<= 0.9){
            return 1;
        }else if(v > 0.9 && v<=1){
            return 0;
        }
        return 0;
    }

    public float[] SerilizebleChooseCourse(ChooseCourse chooseCourse){
        float[] score = new float[7];
        score[0] = chooseCourse.getQ1();
        score[1] = chooseCourse.getQ2();
        score[2] = chooseCourse.getQ3();
        score[3] = chooseCourse.getQ4();
        score[4] = chooseCourse.getQ5();
        score[5] = chooseCourse.getQ6();
        score[6] = chooseCourse.getQ7();
        return score;
    }

    public float[] SerilizebleCourseStandard(Coursestandard coursestandard){
        float[] standard = new float[7];
        standard[0] = coursestandard.getQ1();
        standard[1] = coursestandard.getQ2();
        standard[2] = coursestandard.getQ3();
        standard[3] = coursestandard.getQ4();
        standard[4] = coursestandard.getQ5();
        standard[5] = coursestandard.getQ6();
        standard[6] = coursestandard.getQ7();
        return standard;
    }
}
